import base64
import re
from time import sleep

import cv2
import ddddocr
import numpy as np
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.wait import WebDriverWait  # 这个是为显隐式等待提供方法的模块
from selenium.webdriver.support import expected_conditions as EC  # 这个是为显示等待提供定位功能的模块
from skimage.metrics import structural_similarity

options = webdriver.ChromeOptions()  # 创建谷歌浏览器的options对象来接收浏览器的相关设置

options.add_argument('--start-maximized')  # 最大化窗口
options.add_argument('--incognito')  # 无痕浏览
options.add_argument('--disable-extensions')  # 禁用浏览器的扩展程序,避免干扰网站的打开
options.add_experimental_option("detach", True)  # 禁止浏览器自动关闭
options.add_experimental_option('excludeSwitches', ['enable-automation'])
options.add_experimental_option('useAutomationExtension', False)

# options.add_argument('--headless')
# options.add_argument('user-agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"')
# options.add_argument('--disable-gpu')

driver = webdriver.Chrome(options)  # 创建谷歌浏览器驱动对象
det = ddddocr.DdddOcr(det=True)  # 创建对象

driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
    'source': '''
    Object.defineProperty(navigator, 'webdriver',{get:() => false})
    '''
})

driver.get('https://captcha2.scrape.center/')

wait = WebDriverWait(driver, 10)  # # 设置等待时间

# titles = driver.find_elements(By.CLASS_NAME, 'm-b-sm')
username_inp, password_inp = wait.until(
    EC.presence_of_all_elements_located((By.CLASS_NAME, 'el-input__inner'))
)

username_inp.send_keys('admin')
password_inp.send_keys('admin')

wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, '.el-button.el-button--primary'))).click()
print(1)

while True:
    # 得到背景图片数据
    bg_url = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_item_wrap'))).get_attribute('style')
    bg_url = re.findall(r'url\("(.*?)"\)', bg_url)[0]
    bg_res = requests.get(bg_url)

    bg_img = wait.until(EC.presence_of_element_located((By.CLASS_NAME, 'geetest_item_img')))
    bg_width = bg_img.rect['width']
    bg_height = bg_img.rect['height']

    bboxes = det.detection(bg_res.content)  # 找到图片中的点击坐标，目标检测
    print(bboxes)  # 识别结果[[150, 181, 220, 251], [26, 346, 64, 383], [0, 346, 28, 380], [133, 68, 200, 133]]

    # im = cv2.imdecode(np.frombuffer(图片的字节数据,np.uint8),cv2.IMREAD_COLOR)
    im = cv2.imdecode(np.frombuffer(bg_res.content, np.uint8), cv2.IMREAD_COLOR)  # opencv直接读取字节数据

    # 划分题目与答案
    clicks_data = []  # 题目目标 要点击的内容 [[[坐标],[图片数据]],[],[]]  坐标数据是为了好画图  图片数据数是为了好做对比
    ans_data = []  # 答案

    for bbox in bboxes:  # [150, 181, 220, 251]
        # 得到每一个可能是目标的的矩形范围
        x1, y1, x2, y2 = bbox  # 1左上角 2右下角
        # 对图片进行切片后 将图片划分成题目与答案 将答案进行排序 再将答案图片与题目图片进行对比得出点击的顺序
        # 对图片进行切片
        img_data = im[y1:y2 + 1, x1:x2 + 1]
        # 判断图片是题目还是答案
        if y1 < 340:
            clicks_data.append([bbox, img_data])
        else:
            ans_data.append([bbox, img_data])
        # 将答案进行排序  制定点击顺序 以答案图片的左上角的x进行排序
    ans_data.sort(key=lambda x: x[0][0])

    # 将每个题目与每个答案进行对比 结构相似性
    for ans_bbox, ans_img in ans_data:
        max_ssim = 0  # 最大相似度
        max_bbox = None  # 最大相似度的点击坐标
        max_i = 0  # 选中元素的坐标
        i = 0
        # 得到每张答案图片的信息
        # 将每张图片的颜色转换成灰度
        ans_img = cv2.cvtColor(ans_img, cv2.COLOR_BGR2GRAY)
        # print(ans_img.shape)    #(35, 29)  高35 宽 29
        for clicks_bbox, clicks_img in clicks_data:
            clicks_img = cv2.cvtColor(clicks_img, cv2.COLOR_BGR2GRAY)
            # 得到点击图的尺寸
            h, w = clicks_img.shape
            # 对答案图片进行缩放变成和选项图像一样的尺寸
            ans_img = cv2.resize(ans_img, (w, h))
            # 再计算结构相似性
            ssim = structural_similarity(clicks_img, ans_img, channel_axis=1)  # 彩色图channel_axis=2
            print(ans_bbox, clicks_bbox)
            print(ssim)

            if ssim > max_ssim:
                max_ssim = ssim
                max_bbox = clicks_bbox
                max_i = i
            i += 1

        clicks_data.pop(max_i)  # 去掉相似度最大的哪个因为我已经点击了

        mouse = webdriver.ActionChains(driver)
        mouse.move_to_element_with_offset(
            bg_img, max_bbox[0] + 20 - bg_width / 2, max_bbox[1] + 20 - bg_height / 2
        ).click().perform()
        sleep(1)

        # 得到每张题目图片的信息
    # 点击确认
    wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, 'geetest_commit'))).click()
    sleep(1)

    is_success = re.findall(r'登陆成功', driver.page_source)  # 成功准则  能找到登陆成功
    # 成功就结束识别就循环
    if is_success:
        print(is_success)
        break
    else:
        print('登陆失败')
        sleep(3)

input()
driver.quit()
